#include "sdl_surface.h"


sdl::Surface::Surface()
: _surface(NULL)
{
	sdl::Event::getInstance()->addListener(this);
}


void sdl::Surface::setVideoMode(
    int width, int height, Uint32 flags) throw (sdl::Exception)
{
	_surface = SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE | flags);
	if (_surface == NULL)
		throw sdl::Exception("could not set video mode");
}


void sdl::Surface::putPixel(int x, int y, const glm::vec3& color)
{
	if (x < 0 || x >= _surface->w || y < 0 || y >= _surface->h)
		return;

	Uint8 r = Uint8(glm::clamp(255 * color.r, 0.f, 255.f));
	Uint8 g = Uint8(glm::clamp(255 * color.g, 0.f, 255.f));
	Uint8 b = Uint8(glm::clamp(255 * color.b, 0.f, 255.f));

	Uint32* p = (Uint32*)_surface->pixels + y * _surface->pitch / 4 + x;
	*p = SDL_MapRGB(_surface->format, r, g, b);
}

void sdl::Surface::getpixel(int x, int y, glm::vec3* color)
{
    unsigned int pixel = ((unsigned int*)_surface->pixels)
                [y * (_surface->pitch / sizeof(unsigned int)) + x];
    color->r = ((pixel >> 16) & 0xff) / 255.f;
    color->g = ((pixel >> 8) & 0xff) / 255.f;
    color->b = (pixel & 0xff) / 255.f;
}


void sdl::Surface::fill(SDL_Rect* rc, Uint32 color)
{
	SDL_FillRect(_surface, rc, color);
}


void sdl::Surface::saveBmp(const char* fname)
{
	SDL_SaveBMP(_surface, fname);
}


void sdl::Surface::update()
{
	if (SDL_MUSTLOCK(_surface))
		SDL_LockSurface(_surface);

	// Notify listeners
	fire(sdl::SurfaceListener::Update(), this);

	if (SDL_MUSTLOCK(_surface))
		SDL_UnlockSurface(_surface);
	SDL_UpdateRect(_surface, 0, 0, 0, 0);
}


void sdl::Surface::on(sdl::EventListener::NewEvent, const SDL_Event* e) throw()
{
	switch (e->type) {
	case SDL_VIDEORESIZE:
	case SDL_VIDEOEXPOSE:
		// Redraw
		update();
		break;
	}
}

